
//
// 120512 - AH - (Midtun) Created.
//

package org.soekrat.engine.socraton;

import java.util.ArrayList;
import java.util.List;

import org.japril.jutil.CharArrayPrintWriter;
import org.soekrat.AttributeObject;

/**
 * <p>
 *   Object that compiles Socratons service protocol XML.
 * </p>
 * @author Arne Halvorsen (AH)
 * @author Laetitia Le Chatton (LLC)
 */
public final class SocratonsXmlProtocolCompiler 
{
  private String m_method=null;
  
  private List<AttributeObject> m_socs=new ArrayList<AttributeObject>();
  
  private AttributeObject m_curr=null;
  
  /**
   * <p>
   *   Constructor.
   * </p>
   */
  public SocratonsXmlProtocolCompiler(){}
  
  /**
   * <p>
   *   Sets method.
   * </p>
   * @param m Method name.
   * @return {@code this}.
   */
  public SocratonsXmlProtocolCompiler method(String m)
  { 
    m_method=m; 
    return this; 
  }
  
  /**
   * <p>
   *   Adds 
   *   {@link Socraton} to be mention in XML.
   * </p>
   * @param s {@code Socraton}.
   * @return {@code this}.
   */
  public SocratonsXmlProtocolCompiler socraton(Socraton s)
  {
    m_curr=new AttributeObject();
    m_curr.setAttribute("socraton", s);
    m_socs.add(m_curr);
    return this;
  }
  
  /**
   * <p>
   *   Sets the 'who' parameter to be included in XML for last 
   *   {@link Socraton} added.
   * </p>
   * @param who Name on who.
   * @return {@code this}.
   */
  public SocratonsXmlProtocolCompiler who(String who)
  {
    m_curr.setAttribute("who", who);
    return this;
  }
  
  /**
   * <p>
   *   Compiles.
   * </p>
   * @return XML.
   */
  public String compile()
  {
    CharArrayPrintWriter capw=new CharArrayPrintWriter();
    
    StringBuilder sb=new StringBuilder();
    
    capw.println("<?xml version='1.0'?>");
    
    sb.append("<socratons");
    if (m_method!=null) sb.append(" method='").append(m_method).append("'");
    
    if (m_socs.isEmpty()) sb.append(" />");
    else                  sb.append(">");
    
    capw.println(sb);
    
    for (AttributeObject curr : m_socs)
    {
      Socraton s=(Socraton)curr.getAttribute("socraton");
      String who=curr.getString("who");
      
      if (s!=null)
      {
        sb.setLength(0);
        sb.append("  <socraton id='").append(s.getId().toString())
          .append("'");
        if (who!=null) sb.append(" who='").append(who).append("'");
        
        List<String> contexts=s.getContexts();
        if (contexts.isEmpty())
        {
          sb.append(" />");
          capw.println(sb);
          return capw.toString();
        }
        else
        {
          sb.append(" >");
          capw.println(sb);
          for (String context : contexts)
          {
            Bison[] bisons=s.getBisons(context);
            if (bisons.length>0)
            {
              sb.setLength(0);
              sb.append("    <context name='").append(context).append("' >");
              capw.println(sb);
              for (Bison bison : bisons)
              {
                sb.setLength(0);
                sb.append("      <bison>").append(bison.getLocation())
                  .append("</bison>");
                capw.println(sb);
              }
              capw.println("    </context>");
            }
          }
          capw.println("  </socraton>");
        }
      }
    }
    
    capw.println("</socratons>");
    
    return capw.toString();
  }
  
  /**
   * <p>
   *   Simple demo/test program.
   * </p>
   * @param args Command line arguments, not used.
   */
  public static void main(String[] args)
  {
    Socraton s0=new Socraton("Arne");
    s0.addBison("photo", new Bison("Nikon"));
    s0.addBison("food", new Bison("Horror"));
    
    Socraton s1=new Socraton("Laetitia");
    s1.addBison("art", new Bison("painting"));
    s1.addBison("art", new Bison("CM"));
    s1.addBison("food", new Bison("Gourmet"));
    
    SocratonsXmlProtocolCompiler compiler=new SocratonsXmlProtocolCompiler();
    
    compiler.method("update")
            .socraton(s0).who("test-program")
            .socraton(s1).who("something-else");
    
    String xml=compiler.compile();
    
    System.out.println(xml);
  }
}
